<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { message, Upload } from 'ant-design-vue';
import type { UploadFile, UploadProps } from 'ant-design-vue';
import Api from '@/api';

defineOptions({
  name: 'AvatarUpload',
  inheritAttrs: false,
});

type FileType = Parameters<NonNullable<UploadProps['beforeUpload']>>[0];

const modelValue = defineModel<any>('fileData');
const isSuccessCheck = ref(true);

const fileList = ref<UploadFile[]>([]);

interface errorType {
  row: number;
  errors: string[];
}
const errorList = ref<errorType[]>();

const beforeUpload = (file: FileType) => {
  //验证文件必须是excel
  if (!file.name.endsWith('.xlsx') && !file.name.endsWith('.xls')) {
    message.error('请上传excel文件');
    return false;
  }

  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isLt10M) {
    message.error('文件必须小于10MB!');
  }

  return isLt10M;
};

const uploadFile = async (file: FileType) => {
  errorList.value = [];
  modelValue.value = [];
  const res = await Api.businessTodo.todoExcelImportCheckData({ file });
  if (res.msg && res.msg === '数据校验成功') {
    isSuccessCheck.value = true;
    modelValue.value = res.jsonData;
  } else {
    isSuccessCheck.value = false;
    errorList.value = res.error;
  }
};

const customRequest: UploadProps['customRequest'] = async options => {
  await uploadFile(options.file as FileType);
};

const handleChange: UploadProps['onChange'] = ({ file }) => {
  file.status = 'done';
};

const handleRemove: UploadProps['onRemove'] = async file => {
  fileList.value = [];
  modelValue.value = [];
  errorList.value = [];
};

const init = () => {
  fileList.value = [];
  modelValue.value = [];
  errorList.value = [];
  isSuccessCheck.value = true;
};
defineExpose({
  init,
});
</script>

<template>
  <Upload
    v-model:file-list="fileList"
    :maxCount="1"
    :custom-request="customRequest"
    @before-upload="beforeUpload"
    @change="handleChange"
    @remove="handleRemove"
  >
    <div class="upload-body">
      <Icon class="upload-icon" icon="ant-design:upload-outlined" />
      <div class="ant-upload-text">点击或者拖拽上传</div>
    </div>
  </Upload>
  <div
    class="check-result success"
    v-if="fileList.length > 0 && isSuccessCheck"
  >
    <Icon class="upload-icon" icon="ant-design:check-circle-outlined" />
    校验成功
  </div>
  <div
    class="check-result failed"
    v-if="fileList.length > 0 && !isSuccessCheck"
  >
    <Icon class="upload-icon" icon="ant-design:close-circle-outlined" />
    校验失败
  </div>
  <div class="error-style" v-if="errorList && errorList.length > 0">
    <div class="error-item">
      <div class="error-item-div">序号</div>
      <div class="error-item-div">
        <p>错误信息</p>
      </div>
    </div>
    <div class="error-item" v-for="(item, index) in errorList" :key="index">
      <div class="error-item-div">{{ item.row }}</div>
      <div class="error-item-div" v-for="elem in item.errors">
        <p>{{ elem }}</p>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
.upload-body {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  width: 100%;
  margin: 20px 0px;
  padding: 20px 0px;
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: pointer;
  overflow: hidden;
}

:deep(.ant-upload-select) {
  display: block !important;
}

.check-result {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 10px;
}
.success {
  color: #42c71a;
}
.failed {
  color: #dd1515;
}

.error-style {
  border: 1px solid #d9d9d9;
  margin: 10px 0px;
  max-height: 300px;
  overflow-y: scroll;
  .error-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .error-item-div {
    width: 50%;
    padding: 10px 10px;
    p {
      margin: 0px;
    }
  }
  .error-item-div:first-child {
    border-right: 1px solid #d9d9d9;
  }
  .error-item:not(:last-child) {
    border-bottom: 1px solid #d9d9d9;
  }
}

.upload-icon {
  width: 40px;
  height: 40px;
}
.ant-upload-drag-icon {
  font-size: 48px;
}
.ant-upload-text {
  margin-top: 8px;
}
.ant-upload-hint {
  margin-top: 8px;
  color: rgba(0, 0, 0, 0.45);
}
</style>
